home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / elvis172.zip / opts.c < prev    next >
C/C++ Source or Header  |  1993-03-28  |  19KB  |  814 lines

  1. /* opts.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the code that manages the run-time options -- The 
  12.  * values that can be modified via the "set" command.
  13.  */
  14.  
  15. #include "config.h"
  16. #include "vi.h"
  17. #include "ctype.h"
  18. #ifndef NULL
  19. #define NULL (char *)0
  20. #endif
  21.  
  22. /* maximum width to permit for strings, including ="" */
  23. #define MAXWIDTH 20
  24.  
  25. /* These are the default values of all options */
  26. char    o_autoindent[1] =    {FALSE};
  27. char    o_autoprint[1] =    {TRUE};
  28. char    o_autotab[1] =        {TRUE};
  29. char    o_autowrite[1] =     {FALSE};
  30. char    o_columns[3] =        {80, 32, ~0};
  31. char    o_directory[30] =    TMPDIR;
  32. char    o_edcompatible[1] =    {FALSE};
  33. char    o_equalprg[80] =    {"fmt"};
  34. char    o_errorbells[1] =    {TRUE};
  35. char    o_exrefresh[1] =    {TRUE};
  36. char    o_ignorecase[1] =    {FALSE};
  37. char    o_keytime[3] =        {2, 0, 50};
  38. char    o_keywordprg[80] =    {KEYWORDPRG};
  39. char    o_lines[3] =        {25, 2, 96};
  40. char    o_list[1] =        {FALSE};
  41. char    o_number[1] =        {FALSE};
  42. char    o_readonly[1] =        {FALSE};
  43. char    o_remap[1] =        {TRUE};
  44. char    o_report[3] =        {5, 1, 127};
  45. char    o_scroll[3] =        {12, 1, 127};
  46. char    o_shell[60] =        SHELL;
  47. char    o_shiftwidth[3] =    {8, 1, ~0};
  48. char    o_sidescroll[3] =    {8, 1, 40};
  49. char    o_sync[1] =        {NEEDSYNC};
  50. char    o_tabstop[3] =        {8, 1, 40};
  51. char    o_term[30] =        "?";
  52. char    o_flash[1] =        {TRUE};
  53. char    o_warn[1] =        {TRUE};
  54. char    o_wrapscan[1] =        {TRUE};
  55.  
  56. #ifndef CRUNCH
  57. char    o_beautify[1] =        {FALSE};
  58. char    o_exrc[1] =        {FALSE};
  59. char    o_mesg[1] =        {TRUE};
  60. char    o_more[1] =        {TRUE};
  61. char    o_nearscroll[3] =    {15, 0, ~0};
  62. char    o_novice[1] =        {FALSE};
  63. char    o_prompt[1] =        {TRUE};
  64. char    o_taglength[3] =    {0, 0, 30};
  65. char    o_tags[256] =        {"tags"};
  66. char    o_terse[1] =        {FALSE};
  67. char    o_window[3] =        {0, 1, 24};
  68. char    o_wrapmargin[3] =    {0, 0, ~0};
  69. char    o_writeany[1] =        {FALSE};
  70. #endif
  71.  
  72. #ifndef NO_ERRLIST
  73. char    o_cc[30] =        {CC_COMMAND};
  74. char    o_make[30] =        {MAKE_COMMAND};
  75. #endif
  76.  
  77. #ifndef NO_CHARATTR
  78. char    o_charattr[1] =        {FALSE};
  79. #endif
  80.  
  81. #ifndef NO_DIGRAPH
  82. char    o_digraph[1] =        {FALSE};
  83. char    o_flipcase[80]
  84. # ifdef CS_IBMPC
  85.     = {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
  86. # endif
  87. # ifdef CS_LATIN1
  88.     /* initialized by initopts() */
  89. # endif
  90.     ;
  91. #endif
  92.  
  93. #ifndef NO_SENTENCE
  94. char    o_hideformat[1] =    {FALSE};
  95. #endif
  96.  
  97. #ifndef NO_EXTENSIONS
  98. char    o_inputmode[1] =    {FALSE};
  99. char    o_ruler[1] =        {FALSE};
  100. #endif
  101.  
  102. #ifndef NO_MAGIC
  103. char    o_magic[1] =        {TRUE};
  104. #endif
  105.  
  106. #ifndef NO_MODELINES
  107. char    o_modelines[1] =    {FALSE};
  108. #endif
  109.  
  110. #ifndef NO_SENTENCE
  111. char    o_paragraphs[30] =    "PPppIPLPQP";
  112. char    o_sections[30] =    "NHSHSSSEse";
  113. #endif
  114.  
  115. #if MSDOS
  116. char    o_pcbios[1] =        {TRUE};
  117. #endif
  118.  
  119. #ifndef NO_SHOWMATCH
  120. char    o_showmatch[1] =    {FALSE};
  121. #endif
  122.  
  123. #ifndef    NO_SHOWMODE
  124. char    o_smd[1] =        {FALSE};
  125. #endif
  126.  
  127. #ifndef NO_TAGSTACK
  128. char    o_tagstack[1] =        {TRUE};
  129. #endif
  130.  
  131.  
  132.  
  133. /* The following describes the names & types of all options */
  134. #define BOOL    0
  135. #define    NUM    1
  136. #define    STR    2
  137. #define SET    0x01    /* this option has had its value altered */
  138. #define CANSET    0x02    /* this option can be set at any time */
  139. #define RCSET    0x06    /* this option can be set in a .exrc file only */
  140. #define NOSAVE    0x0a    /* this option should never be saved by mkexrc */
  141. #define WSET    0x20    /* is this the "window" size option? */
  142. #define MR    0x40    /* does this option affect the way text is displayed? */
  143. struct
  144. {
  145.     char    *name;    /* name of an option */
  146.     char    *nm;    /* short name of an option */
  147.     char    type;    /* type of an option */
  148.     char    flags;    /* boolean: has this option been set? */
  149.     char    *value;    /* value */
  150. }
  151.     opts[] =
  152. {
  153.     /* name            type    flags        value */
  154.     { "autoindent",    "ai",    BOOL,    CANSET,        o_autoindent    },
  155.     { "autoprint",    "ap",    BOOL,    CANSET,        o_autoprint    },
  156.     { "autotab",    "at",    BOOL,    CANSET,        o_autotab    },
  157.     { "autowrite",    "aw",    BOOL,    CANSET,        o_autowrite    },
  158. #ifndef CRUNCH
  159.     { "beautify",    "bf",    BOOL,    CANSET,        o_beautify    },
  160. #endif
  161. #ifndef NO_ERRLIST
  162.     { "cc",        "cc",    STR,    CANSET,        o_cc        },
  163. #endif
  164. #ifndef NO_CHARATTR
  165.     { "charattr",    "ca",    BOOL,    CANSET|MR,    o_charattr    },
  166. #endif
  167.     { "columns",    "co",    NUM,    SET|NOSAVE|MR,    o_columns    },
  168. #ifndef NO_DIGRAPH
  169.     { "digraph",    "dig",    BOOL,    CANSET,        o_digraph    },
  170. #endif
  171.     { "directory",    "dir",    STR,    RCSET,        o_directory    },
  172.     { "edcompatible","ed",    BOOL,    CANSET,        o_edcompatible    },
  173.     { "equalprg",    "ep",    STR,    CANSET,        o_equalprg    },
  174.     { "errorbells",    "eb",    BOOL,    CANSET,        o_errorbells    },
  175. #ifndef CRUNCH
  176.     { "exrc",    "exrc",    BOOL,    CANSET,        o_exrc        },
  177. #endif
  178.     { "exrefresh",    "er",    BOOL,    CANSET,        o_exrefresh    },
  179.     { "flash",    "vbell",BOOL,    CANSET,        o_flash        },
  180. #ifndef NO_DIGRAPH
  181.     { "flipcase",    "fc",    STR,    CANSET,        o_flipcase    },
  182. #endif
  183. #ifndef NO_SENTENCE
  184.     { "hideformat",    "hf",    BOOL,    CANSET|MR,    o_hideformat    },
  185. #endif
  186.     { "ignorecase",    "ic",    BOOL,    CANSET,        o_ignorecase    },
  187. #ifndef NO_EXTENSIONS
  188.     { "inputmode",    "im",    BOOL,    CANSET,        o_inputmode    },
  189. #endif
  190.     { "keytime",    "kt",    NUM,    CANSET,        o_keytime    },
  191.     { "keywordprg",    "kp",    STR,    CANSET,        o_keywordprg    },
  192.     { "lines",    "ls",    NUM,    SET|NOSAVE|MR,    o_lines        },
  193.     { "list",    "li",    BOOL,    CANSET|MR,    o_list        },
  194. #ifndef NO_MAGIC
  195.     { "magic",    "ma",    BOOL,    CANSET,        o_magic        },
  196. #endif
  197. #ifndef NO_ERRLIST
  198.     { "make",    "mk",    STR,    CANSET,        o_make        },
  199. #endif
  200. #ifndef CRUNCH
  201.     { "mesg",    "me",    BOOL,    CANSET,        o_mesg        },
  202. #endif
  203. #ifndef NO_MODELINES
  204.     { "modelines",    "ml",    BOOL,    CANSET,        o_modelines    },
  205. #endif
  206. #ifndef CRUNCH
  207.     { "more",    "mo",    BOOL,    CANSET,        o_more        },
  208.     { "nearscroll",    "ns",    NUM,    CANSET,        o_nearscroll    },
  209.     { "novice",    "nov",    BOOL,    CANSET,        o_novice    },
  210. #endif
  211.     { "number",    "nu",    BOOL,    CANSET|MR,    o_number    },
  212. #ifndef NO_SENTENCE
  213.     { "paragraphs",    "para",    STR,    CANSET,        o_paragraphs    },
  214. #endif
  215. #if MSDOS
  216.     { "pcbios",    "pc",    BOOL,    SET|NOSAVE,    o_pcbios    },
  217. #endif
  218. #ifndef CRUNCH
  219.     { "prompt",    "pr",    BOOL,    CANSET,        o_prompt    },
  220. #endif
  221.     { "readonly",    "ro",    BOOL,    CANSET,        o_readonly    },
  222.     { "remap",    "remap",BOOL,    CANSET,        o_remap        },
  223.     { "report",    "re",    NUM,    CANSET,        o_report    },
  224. #ifndef NO_EXTENSIONS
  225.     { "ruler",    "ru",    BOOL,    CANSET,        o_ruler        },
  226. #endif
  227.     { "scroll",    "sc",    NUM,    CANSET,        o_scroll    },
  228. #ifndef NO_SENTENCE
  229.     { "sections",    "sect",    STR,    CANSET,        o_sections    },
  230. #endif
  231.     { "shell",    "sh",    STR,    CANSET,        o_shell        },
  232. #ifndef NO_SHOWMATCH
  233.     { "showmatch",    "sm",    BOOL,    CANSET,        o_showmatch    },
  234. #endif
  235. #ifndef    NO_SHOWMODE
  236.     { "showmode",    "smd",    BOOL,    CANSET,        o_smd        },
  237. #endif
  238.     { "shiftwidth",    "sw",    NUM,    CANSET,        o_shiftwidth    },
  239.     { "sidescroll",    "ss",    NUM,    CANSET,        o_sidescroll    },
  240.     { "sync",    "sy",    BOOL,    CANSET,        o_sync        },
  241.     { "tabstop",    "ts",    NUM,    CANSET|MR,    o_tabstop    },
  242. #ifndef CRUNCH
  243.     { "taglength",    "tl",    NUM,    CANSET,        o_taglength    },
  244.     { "tags",    "tag",    STR,    CANSET,        o_tags        },
  245. #endif
  246. #ifndef NO_TAGSTACK
  247.     { "tagstack",    "tgs",    BOOL,    CANSET,        o_tagstack    },
  248. #endif
  249.     { "term",    "te",    STR,    SET,        o_term        },
  250. #ifndef CRUNCH
  251.     { "terse",    "tr",    BOOL,    CANSET,        o_terse        },
  252.     { "timeout",    "to",    BOOL,    CANSET,        o_keytime    },
  253. #endif
  254. #ifndef CRUNCH
  255.     { "window",    "wi",    NUM,    CANSET|MR|WSET,    o_window    },
  256.     { "wrapmargin",    "wm",    NUM,    CANSET,        o_wrapmargin    },
  257. #endif
  258.     { "wrapscan",    "ws",    BOOL,    CANSET,        o_wrapscan    },
  259. #ifndef CRUNCH
  260.     { "writeany",    "wr",    BOOL,    CANSET,        o_writeany    },
  261. #endif
  262.     { NULL, NULL, 0, CANSET, NULL }
  263. };
  264.  
  265.  
  266. /* This function initializes certain options from environment variables, etc. */
  267. void initopts()
  268. {
  269.     char    *val;
  270.     int    i;
  271.  
  272.     /* set some stuff from environment variables */
  273. #if MSDOS || OS2
  274.     if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
  275. #else
  276.     if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
  277. #endif
  278.     {
  279.         strcpy(o_shell, val);
  280.     }
  281.  
  282.     strcpy(o_term, termtype);
  283. #if MSDOS
  284.     if (strcmp(termtype, "pcbios"))
  285.     {
  286.         o_pcbios[0] = FALSE;
  287.     }
  288.     else
  289.     {
  290.         o_pcbios[0] = TRUE;
  291.     }
  292. #endif
  293.  
  294. #if AMIGA || MSDOS || TOS || OS2
  295.     if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
  296.     ||  (val = getenv("TEMP")))
  297.         strcpy(o_directory, val);
  298. #endif
  299.  
  300. #ifndef CRUNCH
  301.     if ((val = getenv("LINES")) && atoi(val) > 4) /* yes, ASSIGNMENT! */
  302.     {
  303.         LINES = atoi(val);
  304.     }
  305.     if ((val = getenv("COLUMNS")) && atoi(val) > 30) /* yes, ASSIGNMENT! */
  306.     {
  307.         COLS = atoi(val);
  308.     }
  309. #endif
  310.     *o_lines = LINES;
  311.     *o_columns = COLS;
  312.     *o_scroll = LINES / 2 - 1;
  313. #ifndef CRUNCH
  314.     if (o_window[0] == 0)
  315.     {
  316.         o_window[0] = o_window[2] = *o_lines;
  317.     }
  318.     *o_nearscroll = *o_lines;
  319. #endif
  320.  
  321.     /* disable the flash option if we don't know how to do a flash */
  322.     if (!has_VB)
  323.     {
  324.         for (i = 0; opts[i].value != o_flash; i++)
  325.         {
  326.         }
  327.         opts[i].flags &= ~CANSET;
  328.         *o_flash = FALSE;
  329.     }
  330.  
  331. #ifndef NO_DIGRAPH
  332. # ifdef CS_LATIN1
  333.     for (i = 0, val = o_flipcase; i < 32; i++)
  334.     {
  335.         /* leave out the multiply/divide symbols */
  336.         if (i == 23)
  337.             continue;
  338.  
  339.         /* add lower/uppercase pair */
  340.         *val++ = i + 0xe0;
  341.         *val++ = i + 0xc0;
  342.     }
  343.     *val = '\0';
  344. # endif /* CS_LATIN1 */
  345.  
  346.     /* initialize the ctype package */
  347.     _ct_init(o_flipcase);
  348. #else
  349.     _ct_init("");
  350. #endif /* not NO_DIGRAPH */
  351. }
  352.  
  353. /* This function lists the current values of all options */
  354. void dumpopts(all)
  355.     int    all;    /* boolean: dump all options, or just set ones? */
  356. {
  357. #ifndef NO_OPTCOLS
  358.     int    i, j, k;
  359.     char    nbuf[4];    /* used for converting numbers to ASCII */
  360.     int    widths[5];    /* width of each column, including gap */
  361.     int    ncols;        /* number of columns */
  362.     int    nrows;        /* number of options per column */
  363.     int    nset;        /* number of options to be output */
  364.     int    width;        /* width of a particular option */
  365.     int    todump[60];    /* indicies of options to be dumped */
  366.  
  367.     /* step 1: count the number of set options */
  368.     for (nset = i = 0; opts[i].name; i++)
  369.     {
  370.         if (all || (opts[i].flags & SET))
  371.         {
  372.             todump[nset++] = i;
  373.         }
  374.     }
  375.  
  376.     /* step two: try to use as many columns as possible */
  377.     for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
  378.     {
  379.         /* how many would go in this column? */
  380.         nrows = (nset + ncols - 1) / ncols;
  381.  
  382.         /* figure out the width of each column */
  383.         for (i = 0; i < ncols; i++)
  384.         {
  385.             widths[i] = 0;
  386.             for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
  387.             {
  388.                 /* figure out the width of a particular option */
  389.                 switch (opts[todump[k]].type)
  390.                 {
  391.                   case BOOL:
  392.                     if (!*opts[todump[k]].value)
  393.                         width = 2;
  394.                     else
  395.                         width = 0;
  396.                     break;
  397.  
  398.                   case STR:
  399.                     width = 3 + strlen(opts[todump[k]].value);
  400.                     if (width > MAXWIDTH)
  401.                         width = MAXWIDTH;
  402.                     break;
  403.  
  404.                   case NUM:
  405.                     width = 4;
  406.                     break;
  407.                 }
  408.                 width += strlen(opts[todump[k]].name);
  409.  
  410.                 /* if this is the widest so far, widen col */
  411.                 if (width > widths[i])
  412.                 {
  413.                     widths[i] = width;
  414.                 }
  415.             }
  416.  
  417.         }
  418.  
  419.         /* if the total width is narrow enough, then use it */
  420.         for (width = -2, i = 0; i < ncols; i++)
  421.         {
  422.             width += widths[i] + 2;
  423.         }
  424.         if (width < COLS - 1)
  425.         {
  426.             break;
  427.         }
  428.     }
  429.  
  430.     /* step 3: output the columns */
  431.     nrows = (nset + ncols - 1) / ncols;
  432.     for (i = 0; i < nrows; i++)
  433.     {
  434.         for (j = 0; j < ncols; j++)
  435.         {
  436.             /* if we hit the end of the options, quit */
  437.             k = i + j * nrows;
  438.             if (k >= nset)
  439.             {
  440.                 break;
  441.             }
  442.  
  443.             /* output this option's value */
  444.             width = 0;
  445.             switch (opts[todump[k]].type)
  446.             {
  447.               case BOOL:
  448.                 if (!*opts[todump[k]].value)
  449.                 {
  450.                     qaddch('n');
  451.                     qaddch('o');
  452.                     width = 2;
  453.                 }
  454.                 qaddstr(opts[todump[k]].name);
  455.                 width += strlen(opts[todump[k]].name);
  456.                 break;
  457.  
  458.               case NUM:
  459.                 sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
  460.                 qaddstr(opts[todump[k]].name);
  461.                 qaddch('=');
  462.                 qaddstr(nbuf);
  463.                 width = 4 + strlen(opts[todump[k]].name);
  464.                 break;
  465.  
  466.               case STR:
  467.                 qaddstr(opts[todump[k]].name);
  468.                 qaddch('=');
  469.                 qaddch('"');
  470.                 strcpy(tmpblk.c, opts[todump[k]].value);
  471.                 width = 3 + strlen(tmpblk.c);
  472.                 if (width > MAXWIDTH)
  473.                 {
  474.                     width = MAXWIDTH;
  475.                     strcpy(tmpblk.c + MAXWIDTH - 6, "...");
  476.                 }
  477.                 qaddstr(tmpblk.c);
  478.                 qaddch('"');
  479.                 width += strlen(opts[todump[k]].name);
  480.                 break;
  481.             }
  482.  
  483.             /* pad the field to the correct size */
  484.             if (k + nrows <= nset)
  485.             {
  486.                 while (width < widths[j] + 2)
  487.                 {
  488.                     qaddch(' ');
  489.                     width++;
  490.                 }
  491.             }
  492.         }
  493.         addch('\n');
  494.         exrefresh();
  495.     }
  496. #else
  497.     int    i;
  498.     int    col;
  499.     char    nbuf[4];
  500.  
  501.     for (i = col = 0; opts[i].name; i++)
  502.     {
  503.         /* if not set and not all, ignore this option */
  504.         if (!all && !(opts[i].flags & SET))
  505.         {
  506.             continue;
  507.         }
  508.  
  509.         /* align this option in one of the columns */
  510.         if (col > 52)
  511.         {
  512.             addch('\n');
  513.             col = 0;
  514.         }
  515.         else if (col > 26)
  516.         {
  517.             while (col < 52)
  518.             {
  519.                 qaddch(' ');
  520.                 col++;
  521.             }
  522.         }
  523.         else if (col > 0)
  524.         {
  525.             while (col < 26)
  526.             {
  527.                 qaddch(' ');
  528.                 col++;
  529.             }
  530.         }
  531.  
  532.         switch (opts[i].type)
  533.         {
  534.           case BOOL:
  535.             if (!*opts[i].value)
  536.             {
  537.                 qaddch('n');
  538.                 qaddch('o');
  539.                 col += 2;
  540.             }
  541.             qaddstr(opts[i].name);
  542.             col += strlen(opts[i].name);
  543.             break;
  544.  
  545.           case NUM:
  546.             sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
  547.             qaddstr(opts[i].name);
  548.             qaddch('=');
  549.             qaddstr(nbuf);
  550.             col += 4 + strlen(opts[i].name);
  551.             break;
  552.  
  553.           case STR:
  554.             qaddstr(opts[i].name);
  555.             qaddch('=');
  556.             qaddch('"');
  557.             qaddstr(opts[i].value);
  558.             qaddch('"');
  559.             col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
  560.             break;
  561.         }
  562.         exrefresh();
  563.     }
  564.     if (col > 0)
  565.     {
  566.         addch('\n');
  567.         exrefresh();
  568.     }
  569. #endif
  570. }
  571.  
  572. #ifndef NO_MKEXRC
  573. /* This function saves the current configuration of options to a file */
  574. void saveopts(fd)
  575.     int    fd;    /* file descriptor to write to */
  576. {
  577.     int    i;
  578.     char    buf[256], *pos;
  579.  
  580.     /* write each set options */
  581.     for (i = 0; opts[i].name; i++)
  582.     {
  583.         /* if unset or unsettable, ignore this option */
  584.         if ((opts[i].flags & (SET|CANSET|NOSAVE)) != (SET|CANSET))
  585.         {
  586.             continue;
  587.         }
  588.  
  589.         strcpy(buf, "set ");
  590.         pos = &buf[4];
  591.         switch (opts[i].type)
  592.         {
  593.           case BOOL:
  594.             if (!*opts[i].value)
  595.             {
  596.                 *pos++='n';
  597.                 *pos++='o';
  598.             }
  599.             strcpy(pos, opts[i].name);
  600.             strcat(pos, "\n");
  601.             break;
  602.  
  603.           case NUM:
  604.             sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
  605.             break;
  606.  
  607.           case STR:
  608.             sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
  609.             break;
  610.         }
  611.         twrite(fd, buf, (unsigned)strlen(buf));
  612.     }
  613. }
  614. #endif
  615.  
  616.  
  617. /* This function changes the values of one or more options. */
  618. void setopts(assignments)
  619.     char    *assignments;    /* a string containing option assignments */
  620. {
  621.     char    *name;        /* name of variable in assignments */
  622.     char    *value;        /* value of the variable */
  623.     char    *scan;        /* used for moving through strings */
  624.     char    *build;        /* used for copying chars from "scan" */
  625.     char    *prefix;    /* pointer to "neg" or "no" at front of a boolean */
  626.     int    quote;        /* boolean: inside '"' quotes? */
  627.     int    i, j;
  628.  
  629. #ifndef CRUNCH
  630.     /* reset the upper limit of "window" option to lines-1 */
  631.     *o_window = *o_lines - 1;
  632. #endif
  633.  
  634.     /* for each assignment... */
  635.     for (name = assignments; *name; )
  636.     {
  637.         /* skip whitespace */
  638.         if (*name == ' ' || *name == '\t')
  639.         {
  640.             name++;
  641.             continue;
  642.         }
  643.  
  644.         /* after the name, find the value (if any) */
  645.         for (scan = name; isalnum(*scan); scan++)
  646.         {
  647.         }
  648.         if (*scan == '=')
  649.         {
  650.             *scan++ = '\0';
  651.             value = build = scan;
  652.             for (quote = FALSE; *scan && (quote || !isspace(*scan)); scan++)
  653.             {
  654.                 if (*scan == '"')
  655.                 {
  656.                     quote = !quote;
  657.                 }
  658.                 else if (*scan == '\\' && scan[1])
  659.                 {
  660.                     *build++ = *++scan;
  661.                 }
  662.                 else
  663.                 {
  664.                     *build++ = *scan;
  665.                 }
  666.             }
  667.             if (*scan)
  668.                 scan++;
  669.             *build = '\0';
  670.         }
  671.         else /* no "=" so it is probably boolean... */
  672.         {
  673.             if (*scan)
  674.             {
  675.                 *scan++ = '\0';
  676.             }
  677.             value = NULL;
  678.             prefix = name;
  679. #ifndef CRUNCH
  680.             if (!strcmp(name, "novice"))
  681.                 /* don't check for a "no" prefix */;
  682.             else
  683. #endif
  684.             if (prefix[0] == 'n' && prefix[1] == 'o')
  685.                 name += 2;
  686.             else if (prefix[0] == 'n' && prefix[1] == 'e' && prefix[2] == 'g')
  687.                 name += 3;
  688.         }
  689.  
  690.         /* find the variable */
  691.         for (i = 0;
  692.              opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
  693.              i++)
  694.         {
  695.         }
  696.  
  697.         /* change the variable */
  698.         if (!opts[i].name)
  699.         {
  700.             /* only complain about unknown options if we're editing
  701.              * a file;  i.e., if we're not executing the .exrc now.
  702.              */
  703.             if (tmpfd >= 0)
  704.                 msg("invalid option name \"%s\"", name);
  705.         }
  706.         else if ((opts[i].flags & CANSET) != CANSET)
  707.         {
  708.             msg("option \"%s\" can't be altered", name);
  709.         }
  710.         else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
  711.         {
  712.             msg("option \"%s\" can only be set in a %s file", name, EXRC);
  713.         }
  714.         else if (value)
  715.         {
  716.             switch (opts[i].type)
  717.             {
  718.               case BOOL:
  719.                 msg("option \"[no]%s\" is boolean", name);
  720.                 break;
  721.  
  722.               case NUM:
  723.                 j = atoi(value);
  724.                 if (j == 0 && *value != '0')
  725.                 {
  726.                     msg("option \"%s\" must have a numeric value", name);
  727.                 }
  728.                 else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
  729.                 {
  730.                     msg("option \"%s\" must have a value between %d and %d",
  731.                         name, opts[i].value[1], opts[i].value[2] & 0xff);
  732.                 }
  733.                 else
  734.                 {
  735.                     *opts[i].value = atoi(value);
  736.                     opts[i].flags |= SET;
  737.                 }
  738.                 break;
  739.  
  740.               case STR:
  741.                 strcpy(opts[i].value, value);
  742.                 opts[i].flags |= SET;
  743.                 break;
  744.             }
  745.             if (opts[i].flags & MR)
  746.             {
  747.                 redraw(MARK_UNSET, FALSE);
  748.             }
  749. #ifndef CRUNCH
  750.             if (opts[i].flags & WSET)
  751.             {
  752.                 wset = TRUE;
  753.             }
  754. #endif
  755.         }
  756.         else /* valid option, no value */
  757.         {
  758.             if (opts[i].type == BOOL)
  759.             {
  760.                 if (prefix == name)
  761.                     *opts[i].value = TRUE;
  762.                 else if (prefix[1] == 'o')
  763.                     *opts[i].value = FALSE;
  764.                 else
  765.                     *opts[i].value = !*opts[i].value;
  766.  
  767.                 opts[i].flags |= SET;
  768.                 if (opts[i].flags & MR)
  769.                 {
  770.                     redraw(MARK_UNSET, FALSE);
  771.                 }
  772.             }
  773.             else
  774.             {
  775.                 msg("option \"%s\" must be given a value", name);
  776.             }
  777.         }
  778.  
  779.         /* move on to the next option */
  780.         name = scan;
  781.     }
  782.  
  783.     /* special processing ... */
  784.  
  785. #ifndef CRUNCH
  786.     /* if "novice" is set, then ":set report=1 showmode nomagic" */
  787.     if (*o_novice)
  788.     {
  789.         *o_report = 1;
  790. # ifndef NO_SHOWMODE
  791.         *o_smd = TRUE;
  792. # endif
  793. # ifndef NO_MAGIC
  794.         *o_magic = FALSE;
  795. # endif
  796.     }
  797. #endif
  798.  
  799.     /* if "readonly" then set the READONLY flag for this file */
  800.     if (*o_readonly)
  801.     {
  802.         setflag(file, READONLY);
  803.     }
  804.  
  805. #ifndef NO_DIGRAPH
  806.     /* re-initialize the ctype package */
  807.     _ct_init(o_flipcase);
  808. #endif /* not NO_DIGRAPH */
  809.  
  810.     /* copy o_lines and o_columns into LINES and COLS */
  811.     LINES = (*o_lines & 255);
  812.     COLS = (*o_columns & 255);
  813. }
  814.